/*
 * Copyright 2017 Baiyyy
 * @(#)DRealTimeRptIstr.java
 */

package com.byyy.ccts.modules.cc.handle.istr.v23;

import com.byyy.ccts.core.utils.DateUtils;
import com.byyy.ccts.core.utils.HexUtils;
import com.byyy.ccts.core.utils.InstructionUtils;
import com.byyy.ccts.modules.cc.Global;
import com.byyy.ccts.modules.cc.entity.ccts.TSHumiture;
import com.byyy.ccts.modules.cc.entity.istr.InstructionMdl;
import com.byyy.ccts.modules.cc.entity.istr.ext.BaseStationData;
import com.byyy.ccts.modules.cc.entity.istr.ext.WarningThresholdData;
import com.byyy.ccts.modules.cc.entity.istr.v23.DRealTimeReportMdl;
import com.byyy.ccts.modules.cc.handle.istr.IHandler;
import org.springframework.stereotype.Service;

import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 178D协议V2.3 实时消息上报处理类
 * Created by DELL on 2018-4-28.
 */
@Service("dRealTimeRptIstrHdl")
public class DRealTimeRptIstrHdl extends IHandler {

    /**
     * 实时消息上报指令解析
     * 1.校验(已提出共通)
     * 2.解析实时消息上报指令
     * 3.将数据插入数据库
     * 4.应答(已提出共通)
     * @param instructions
     * @return
     */
    @Override
    public byte[] handle(byte[] instructions) {
        logger.debug("实时数据V2.3 开始执行");
        // 解析实时消息上报指令
        InstructionMdl istrMdl = this.generateInstructionModel(instructions);
        DRealTimeReportMdl rtReport = new DRealTimeReportMdl();
        rtReport.setSequenceNum(istrMdl.getSequenceNum());
        rtReport.setDeviceId(istrMdl.getDeviceId());

        // GMS时间
        byte[] gmsTime = new byte[6];
        for (int i = 0; i < 6; i++) {
            gmsTime[i] = instructions[15 + i];
        }
        rtReport.setGsmTime(gmsTime);

        // 信号量
        rtReport.setSemaphore(instructions[21]);
        // 电池电量
        rtReport.setElectric(instructions[22]);
        // 温度符号
        rtReport.setTempSymbol(instructions[23]);
        // 温度整数部分
        rtReport.setTempeInt(instructions[24]);
        // 温度小数部分
        rtReport.setTempDec(instructions[25]);
        // 环境温度符号
        rtReport.setEnvTempSymbol(instructions[26]);
        // 环境温度整数部分
        rtReport.setEnvTempeInt(instructions[27]);
        // 环境温度小数部分
        rtReport.setEnvTempeDec(instructions[28]);
        // 湿度值
        rtReport.setHumidity(instructions[29]);
        // 报警标志状态
        byte[] warn = new byte[4];
        warn[0] = instructions[30];
        warn[1] = instructions[31];
        warn[1] = instructions[32];
        warn[1] = instructions[33];
        rtReport.setWarn(warn);
        // 扩展信息-(循环取报警阈值, 基站信息,光感量信息)
        int offset = 0;
        int perExtLen = 0;
        byte[] dest = null;
        for (int i = 0; i < 3; i++) {
            // 判断接下来的是否为扩展信息(扩展信息起始位置(34) + 偏移量 + 校验位(1) + 包尾(1) >= 数组长度)
            if ((36 + offset) >= instructions.length) {
                break;
            }
            // 获取每条信息长度，用作偏移量
            perExtLen = instructions[35 + offset];
            // 重组数组
            dest = new byte[perExtLen + 2];
            for (int j = 0; j < dest.length; j++) {
                dest[j] = instructions[34 + offset + j];
            }
            // 将解析结果保存到DRealTimeReportMdl
            parseExtInfo(dest, rtReport);
            // 偏移量 += 每条信息长度 + 1(扩展信息ID长度) + 1(扩展信息长度的长度)
            offset += perExtLen + 2;
        }

        this.insert(rtReport);

        logger.debug("实时数据V2.3 执行结束");
        return InstructionUtils.generateCommResponse(rtReport, Global.ISTR_D_REALTIME_REPORT);
    }

    /**
     * 解析扩展信息
     * @param istrData
     * @param realTimeReportMdl
     */
    private void parseExtInfo(byte[] istrData, DRealTimeReportMdl realTimeReportMdl) {
        switch (istrData[0]) {
            case Global.EXT_0X01 :
                realTimeReportMdl.setExtInfo1Id(istrData[0]);
                realTimeReportMdl.setExtInfo1Lenth(istrData[1]);
                WarningThresholdData extInfo1 = new WarningThresholdData();
                extInfo1.setTempSymbolH(istrData[2]);
                extInfo1.setTempIntH(istrData[3]);
                extInfo1.setTempDecH(istrData[4]);
                extInfo1.setTempSymbolL(istrData[5]);
                extInfo1.setTempIntL(istrData[6]);
                extInfo1.setTempDecL(istrData[7]);
                extInfo1.setHumidityH(istrData[8]);
                extInfo1.setHumidityL(istrData[9]);
                extInfo1.setElectricL(istrData[10]);
                realTimeReportMdl.setWarningThresholdData(extInfo1);
                break;
            case Global.EXT_0X02 :
                realTimeReportMdl.setExtInfo2Id(istrData[0]);
                realTimeReportMdl.setExtInfo2Lenth(istrData[1]);
                int len = ((int) istrData[1]) / 12;
                BaseStationData baseStationData = null;
                List<BaseStationData> baseStationDataList = new ArrayList<>();
                for (int i = 0; i < len; i++) {
                    baseStationData = new BaseStationData();
                    baseStationData.setRxl(istrData[2 + (i * 12)]);
                    baseStationData.setMcc(new byte[]{
                            istrData[3 + (i * 12)],
                            istrData[4 + (i * 12)]
                    });
                    baseStationData.setMnc(istrData[5 + (i * 12)]);
                    baseStationData.setCellid(new byte[]{
                            istrData[6 + (i * 12)],
                            istrData[7 + (i * 12)],
                            istrData[8 + (i * 12)],
                            istrData[9 + (i * 12)]
                    });
                    baseStationData.setLac(new byte[]{
                            istrData[10 + (i * 12)],
                            istrData[11 + (i * 12)],
                            istrData[12 + (i * 12)],
                            istrData[13 + (i * 12)]
                    });
                    baseStationDataList.add(baseStationData);
                }
                realTimeReportMdl.setBaseStationData(baseStationDataList);
                break;
            case Global.EXT_0X03 :
                realTimeReportMdl.setExtInfo3Id(istrData[0]);
                realTimeReportMdl.setExtInfo3Lenth(istrData[1]);
                realTimeReportMdl.setLightPerceptionData(new byte[]{
                        istrData[2],
                        istrData[3],
                        istrData[4],
                        istrData[5]
                });
                break;
        }
    }

    /**
     *  将实时数据插入数据库中
     */
    private void insert(DRealTimeReportMdl model) {
        TSHumiture tsHumiture = new TSHumiture();
        float temp = 0;
        tsHumiture.setDeviceSn(HexUtils.bytesToHexFun3(model.getDeviceId()));
        tsHumiture.setCollectTime(new Timestamp(DateUtils.structure(
                model.getGsmTime()[0], model.getGsmTime()[1] - 1,
                model.getGsmTime()[2], model.getGsmTime()[3],
                model.getGsmTime()[4], model.getGsmTime()[5]).getTime()));

        // 设置温度值,注意零下的情况
        temp = Float.valueOf((int) model.getTempeInt() + "." + (int) model.getTempDec());
        if (!(Global.OTH_TEMP_SYMBOL_PLUS == model.getTempSymbol())) {
            temp = -temp;
        }
        tsHumiture.setTemperature(temp);
        tsHumiture.setSemaphore(model.getSemaphore());
        tsHumiture.setElectric(model.getElectric());
        tsHumiture.setHumidity(model.getHumidity());
//        tsHumiture.setCellId(HexUtils.bytes2int(model.getBaseStationData().get(0).getCellid()));
//        tsHumiture.setLac(HexUtils.bytes2int(model.getBaseStationData().get(0).getLac()));

        this.insertHumiture(Arrays.asList(tsHumiture));
    }

}
